package top.jacktgq.concurrent_utils.pool;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import top.jacktgq.utils.LogUtils;
import top.jacktgq.utils.Sleeper;
/**
 * 
 * @Title: SubmitTaskAndGetResultDemo.java 
 * @Package top.jacktgq.concurrent_utils.pool 
 * @Description: 任务的提交，以及获取任务执行完成的返回结果
 * @author CandyWall   
 * @date 2020年11月4日 下午2:52:09 
 * @version V1.0
 */
public class SubmitTaskAndGetResultDemo {
	public static void main(String[] args) {
		testSubmit();
		//testInvokeAll();
		//testInvokeAny();
	}

	//提交任务task，用返回值Future获得任务执行结果
	private static void testSubmit() {
		ExecutorService threadPool = Executors.newFixedThreadPool(2);
		Future<String> future = threadPool.submit(() -> {
			LogUtils.log("testSubmit", "Running...");
			Sleeper.sleep(10);
			return "OK";
		});
		try {
			LogUtils.log("testSubmit", future.get());
			System.out.println("hello");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	//提交tasks中所有任务，可以设置超时时间
	private static void testInvokeAll() {
		ExecutorService threadPool = Executors.newFixedThreadPool(2);
		try {
			List<Future<Object>> futures = threadPool.invokeAll(Arrays.asList(
				() -> {
					LogUtils.log("testInvokeAll", "begin...");
					Sleeper.sleep(1);
					return "1";
				},
				() -> {
					LogUtils.log("testInvokeAll", "begin...");
					Sleeper.sleep(1);
					return "2";
				},
				() -> {
					LogUtils.log("testInvokeAll", "begin...");
					Sleeper.sleep(1);
					return "3";
				}
			), 3, TimeUnit.SECONDS);
			futures.forEach(f -> {
				try {
					LogUtils.log("testInvokeAll", "" + f.get());
				} catch (Exception e) {
					e.printStackTrace();
				}
			});
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	//调剂tasks中所有任务，哪个任务先成功执行完毕，返回次任务执行结果，其他任务取消，可以设置超时时间
	private static void testInvokeAny() {
		ExecutorService threadPool = Executors.newFixedThreadPool(2);
		try {
			String future = threadPool.invokeAny(Arrays.asList(
				() -> {
					LogUtils.log("testInvokeAny", "begin...");
					//这里不能使用自己封装的线程睡眠工具类，
					//因为我自定义的工具类内部将InterruptedException异常捕获了，
					//会导致jdk定义的线程池在其中一个任务先执行完了，然后取消其他任务执行的时候出现问题，
					//具体问题是：调用Thread.interrupt()方法打断正在睡眠中的线程，
					//会报InterruptedException异常，而这个异常发生的时候，打断标记位会置为false，
					//系统的线程池类内部捕获不到异常，将标志位改为true，将导致导致线程的二阶段终止失败，
					//Sleeper.sleep(3000, TimeUnit.MILLISECONDS);
					TimeUnit.SECONDS.sleep(3);
					LogUtils.log("testInvokeAny", "end...");
					return "1";
				},
				() -> {
					LogUtils.log("testInvokeAny", "begin...");
					//Sleeper.sleep(1000, TimeUnit.MILLISECONDS);
					TimeUnit.SECONDS.sleep(1);
					LogUtils.log("testInvokeAny", "end...");
					return "2";
				},
				() -> {
					LogUtils.log("testInvokeAny", "begin...");
					//Sleeper.sleep(2000, TimeUnit.MILLISECONDS);
					TimeUnit.SECONDS.sleep(2);
					LogUtils.log("testInvokeAny", "end...");
					return "3";
				}
			));
			LogUtils.log("testInvokeAny", "" + future);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
